package com.thoughtworks;

import java.util.*;

public class Library {
    private
            String userId;
    public
    InputProcess inputProcess;
    OutputProcess outputProcess;
    public List<User> customers;
    TreeMap<Rentable, Boolean> availableEntities = new TreeMap<Rentable, Boolean>(new Com());
    TreeMap<Rentable, String> checkedOutEntities = new TreeMap<Rentable, String>(new Com());


    Library() {
        inputProcess=new InputProcess();
        outputProcess=new OutputProcess();
        customers = new ArrayList<User>();

        availableEntities.put(new Book("The windmills of god", "Sidney sheldon", 2000), true);
        availableEntities.put(new Book("If tomorrow comes", "Sidney sheldon", 2005), true);

        availableEntities.put(new Book("The windmills of god", "Sidney sheldon", 2000), true);

        availableEntities.put(new Movie("Titanic", "James Cameroon", 1990, 10), true);
        availableEntities.put(new Movie("avatar", "james", 2000, 10), true);
        customers.add(new User("Sai", 111, "sss@gmail.com", "123-1234", "abcd"));
        customers.add(new User("Sai11", 112, "sss1@gmail.com", "120-1234", "abcd"));
        customers.add(new User("Librarian",100,"librarian@gmail.com","111-1111","lib"));

    }

    public String whoHasThisEntity(String entityName) throws NoSuchEntity {


        for (Map.Entry<Rentable,String> entrySet : checkedOutEntities.entrySet()) {
            //Book
            Rentable rentable=entrySet.getKey();
            if (rentable.getEntityName().equals(entityName)) {
                return  entrySet.getValue();

            }

        }


        throw new NoSuchEntity("This book is not in the checked out list");
    }
    public void setCurrentUser(String userId) {
        this.userId = userId;
    }
    public String getCurrentUser(){
        return this.userId;

    }
public boolean logIn(String libraryNumber,String password) throws NotAValidUser {
    for (User user : customers) {
        if (user.getLibraryNumber().equals(libraryNumber) && user.getPassword().equals(password))
            return true;
    }
    throw new NotAValidUser("You are not a valid user.!");
}
    public String getUserName(String libraryNumber) throws NotAValidUser {
        for (User user : customers) {
            if (user.getLibraryNumber().equals(libraryNumber)) {
                return user.getName();
            }
        }
throw new NotAValidUser("You are not a valid user");

    }






    public void listAllEntities() {

        for (Map.Entry<Rentable,Boolean> entity : availableEntities.entrySet()) {


            Rentable rentable =  entity.getKey();

            if (rentable instanceof Book) {

                Book book = (Book) entity.getKey();
                outputProcess.printMenuForBook();
                outputProcess.printAvailableBooks(book);
            }
        }

        for (Map.Entry entity : availableEntities.entrySet()) {

            Rentable rentable = (Rentable) entity.getKey();

            if (rentable instanceof Movie) {
                Movie movie = (Movie) entity.getKey();
                outputProcess.printAllMovies();
                outputProcess.printAvailableMovies(movie);

            }
        }
    }


    public boolean checkOut(String requestedRentableName, String userName, Class rentableClass) throws NoSuchEntity, NotAValidUser {
        String entityType = rentableClass.getSimpleName().toLowerCase();
        if (userName.equals(""))
            throw new NotAValidUser("Log in before you check out");
        for (Map.Entry<Rentable, Boolean> entity : availableEntities.entrySet()) {
            boolean isAvailable = entity.getValue();
            Rentable rentable = entity.getKey();
            if (rentable.getEntityName().equals(requestedRentableName) && rentableClass.isInstance(rentable) && isAvailable) {
                availableEntities.put(entity.getKey(), false);
                checkedOutEntities.put(entity.getKey(), userName);
                return true;
            }
        }
        throw new NoSuchEntity("No such " + entityType + " is available in our library");
    }

    public boolean returnRentable(String bookName, String userName, Class rentableClass) throws NoSuchEntity, NotAValidUser {
        if (userName.equals(""))
            throw new NotAValidUser("Log in before you check out");
        String entityType = rentableClass.getSimpleName().toLowerCase();

        for (Map.Entry<Rentable, String> entityEntry : checkedOutEntities.entrySet()) {
            Rentable entity = entityEntry.getKey();
            String libraryNumber = entityEntry.getValue();


            if (entity.getEntityName().equals(bookName) && libraryNumber.equals(userName) && rentableClass.isInstance(entity)) {
                checkedOutEntities.remove(entityEntry.getKey());
                Rentable returnedEntity = entityEntry.getKey();
                availableEntities.put(returnedEntity, true);
                return true;
            }


        }


        throw new NoSuchEntity("not a valid  "+entityType+" "+ "to return!");

    }

    public User seeMyDetails(String libraryNumber) throws NotAValidUser {
        for (User user : customers) {
            if (user.getLibraryNumber().equals(libraryNumber)) {

                return user;
            }
        }
throw new NotAValidUser("You are not a valid user!");
    }


    public String logOut(String libraryNumber) throws NotAValidUser {
        if (libraryNumber.equals("") )
            throw new NotAValidUser("You are not a valid user to log out");
        libraryNumber = "";
        userId=libraryNumber;
        return userId;
    }
}

class Com implements Comparator<Rentable> {
    @Override
    public int compare(Rentable o, Rentable o2) {
        return o.getEntityName().compareTo(o2.getEntityName());

    }
}


